
import os
import config
import threading
from datetime import datetime
from lib.tools.compat import String as StringCompat
from sqlalchemy import Column, Boolean, Integer, Float, String, DateTime, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

__all__ = ['SqliteFactory', 'Connect']

Base = declarative_base()


class SqliteFactory(object):
    _session = None
    _instance = None
    _sqlite_lock = threading.Lock()

    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(SqliteFactory, cls).__new__(cls)
        return cls._instance

    def __init__(self, uri=config.SQLITE_URL, echo=config.STORAGE_ECHO):
        connect_args = {'check_same_thread': False}
        self.engine = create_engine(uri, echo=echo, encoding=config.STORAGE_ENCODING, connect_args=connect_args)
        self.session = sessionmaker(bind=self.engine)
        self.__init_db__()

    def __init_db__(self):
        if not os.path.exists(config.DATA_FOLDER):
            os.mkdir(config.DATA_FOLDER)
        Base.metadata.create_all(self.engine)
        # Base.metadata.create_table(Proxy)

    def session(self):
        if not self._session:
            self._session = self.session()
            self._session.text_factory = str
        return self._session

    def lock(self):
        return self._sqlite_lock.acquire()

    def unlock(self):
        return self._sqlite_lock.release()

    def close(self):
        if self._session:
            self._session.close()
            self._session = None


class Connect(Base):
    __tablename__ = 'connect'
    id = Column('id', Integer, primary_key=True)
    name = Column('name', String(20), nullable=False, unique=True)
    type = Column('type', Integer, nullable=False)
    auth = Column('auth', String(20), nullable=True)
    create_time = Column('create_time', DateTime, nullable=False, default=datetime.now)
    update_time = Column('update_time', DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)


class NodeInfo(Base):
    __tablename__ = 'node_info'
    id = Column('id', Integer, primary_key=True)
    connect_id = Column('connect_id', Integer, nullable=False)
    host = Column('host', String(20), nullable=True)
    port = Column('port', Integer, nullable=True)
    create_time = Column('create_time', DateTime, nullable=False, default=datetime.now)
    update_time = Column('update_time', DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)